﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Data;

namespace Dotway.WPF.Effects
{
    public class WaveEffect : ShaderEffect
    {

        #region Fields

        private static PixelShader pixelShader = new PixelShader();
        private WaveEffectTransform waveTransform = new WaveEffectTransform();

        #endregion Fields
        #region Constructors

        static WaveEffect()
        {
            pixelShader.UriSource = Global.MakePackUri("WaveEffect.ps");
        }

        public WaveEffect()
        {
            // Create bindings to some properties that we need in out transform class. 
            // These properties are also used in the shader.
            Binding frequencyBinding = new Binding("Frequency");
            frequencyBinding.Source = this;
            BindingOperations.SetBinding(waveTransform, WaveEffectTransform.FrequencyProperty, frequencyBinding);

            Binding amplitudeBinding = new Binding("Amplitude");
            amplitudeBinding.Source = this;
            BindingOperations.SetBinding(waveTransform, WaveEffectTransform.AmplitudeProperty, amplitudeBinding);

            PixelShader = pixelShader;

            UpdateShaderValue(InputProperty);
            UpdateShaderValue(FrequencyProperty);
            UpdateShaderValue(AmplitudeProperty);
        }

        #endregion Constructors
        #region Properties

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(WaveEffect), 0);
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }


        public static readonly DependencyProperty FrequencyProperty = DependencyProperty.Register("Frequency", typeof(double), typeof(WaveEffect), new UIPropertyMetadata(10.0, PixelShaderConstantCallback(0)), new ValidateValueCallback(IsValidFrequency));
        public double Frequency
        {
            get { return (double)GetValue(FrequencyProperty); }
            set { SetValue(FrequencyProperty, value); }
        }

        public static bool IsValidFrequency(object value)
        {
            double checkValue = (double)value;

            if (checkValue < 0.0)
            {
                return false;
            }

            return true;
        }


        public static readonly DependencyProperty AmplitudeProperty = DependencyProperty.Register("Amplitude", typeof(double), typeof(WaveEffect), new UIPropertyMetadata(0.2, PixelShaderConstantCallback(1)), new ValidateValueCallback(IsValidAmplitude));
        public double Amplitude
        {
            get { return (double)GetValue(AmplitudeProperty); }
            set { SetValue(AmplitudeProperty, value); }
        }

        public static bool IsValidAmplitude(object value)
        {
            double checkValue = (double)value;

            if (checkValue < 0.0)
            {
                return false;
            }

            return true;
        }        

        #endregion Properties

        /// <summary>
        /// Provide a transform class that can be used for e.g. hit-testing.
        /// This will enable us to interact with the GUI even that an 
        /// effect is applied.
        /// </summary>
        protected override GeneralTransform EffectMapping
        {
            get
            {
                return waveTransform;
            }
        }
    }
}
